5ba86ca2540de234facef51e5fbe1921f4d356de,router/java/src/net/i2p/router/transport/udp/PacketBuilder.java,PacketBuilder,buildSessionConfirmedPacket,#OutboundEstablishState#number#number#number#,730

Before Change


     */
    public UDPPacket buildSessionConfirmedPacket(OutboundEstablishState state, int fragmentNum, int numFragments, byte identity[]) {
        UDPPacket packet = buildPacketHeader(SESSION_CONFIRMED_FLAG_BYTE);
        byte data[] = packet.getPacket().getData();
        int off = HEADER_SIZE;

        InetAddress to = null;
        try {
            to = InetAddress.getByAddress(state.getSentIP());
        } catch (UnknownHostException uhe) {
            if (_log.shouldLog(Log.ERROR))
                _log.error("How did we think this was a valid IP?  " + state.getRemoteHostId().toString());
            packet.release();
            return null;
        }
        
        // now for the body
        data[off] |= fragmentNum << 4;
        data[off] |= (numFragments & 0xF);
        off++;
        
        int curFragSize = MAX_IDENTITY_FRAGMENT_SIZE;
        if (fragmentNum == numFragments-1) {
            if (identity.length % MAX_IDENTITY_FRAGMENT_SIZE != 0)
                curFragSize = identity.length % MAX_IDENTITY_FRAGMENT_SIZE;
        }
        
        DataHelper.toLong(data, off, 2, curFragSize);
        off += 2;
        
        int curFragOffset = fragmentNum * MAX_IDENTITY_FRAGMENT_SIZE;
        System.arraycopy(identity, curFragOffset, data, off, curFragSize);
        off += curFragSize;
        
        if (fragmentNum == numFragments - 1) {
            DataHelper.toLong(data, off, 4, state.getSentSignedOnTime());
            off += 4;
            
            int paddingRequired = 0;
            // we need to pad this so we're at the encryption boundary
            if ( (off + Signature.SIGNATURE_BYTES) % 16 != 0)
                paddingRequired += 16 - ((off + Signature.SIGNATURE_BYTES) % 16);
            
            // add an arbitrary number of 16byte pad blocks too...
            
            for (int i = 0; i < paddingRequired; i++) {
                data[off] = (byte)_context.random().nextInt(255);
                off++;
            }
            
            // BUG: NPE here if null signature
            System.arraycopy(state.getSentSignature().getData(), 0, data, off, Signature.SIGNATURE_BYTES);
            off += Signature.SIGNATURE_BYTES;
        } else {
            // nothing more to add beyond the identity fragment, though we can
            // pad here if we want.  maybe randomized?

            // pad up so we're on the encryption boundary
            // TODO: why not random data?
            if ( (off % 16) != 0)
                off += 16 - (off % 16);
        } 
        packet.getPacket().setLength(off);
        authenticate(packet, state.getCipherKey(), state.getMACKey());
        
        setTo(packet, to, state.getSentPort());

After Change


     */
    private UDPPacket buildSessionConfirmedPacket(OutboundEstablishState state, int fragmentNum, int numFragments, byte identity[]) {
        UDPPacket packet = buildPacketHeader(SESSION_CONFIRMED_FLAG_BYTE);
        DatagramPacket pkt = packet.getPacket();
        byte data[] = pkt.getData();
        int off = HEADER_SIZE;

        InetAddress to = null;
        try {
            to = InetAddress.getByAddress(state.getSentIP());
        } catch (UnknownHostException uhe) {
            if (_log.shouldLog(Log.ERROR))
                _log.error("How did we think this was a valid IP?  " + state.getRemoteHostId().toString());
            packet.release();
            return null;
        }
        
        // now for the body
        data[off] |= fragmentNum << 4;
        data[off] |= (numFragments & 0xF);
        off++;
        
        int curFragSize = MAX_IDENTITY_FRAGMENT_SIZE;
        if (fragmentNum == numFragments-1) {
            if (identity.length % MAX_IDENTITY_FRAGMENT_SIZE != 0)
                curFragSize = identity.length % MAX_IDENTITY_FRAGMENT_SIZE;
        }
        
        DataHelper.toLong(data, off, 2, curFragSize);
        off += 2;
        
        int curFragOffset = fragmentNum * MAX_IDENTITY_FRAGMENT_SIZE;
        System.arraycopy(identity, curFragOffset, data, off, curFragSize);
        off += curFragSize;
        
        if (fragmentNum == numFragments - 1) {
            DataHelper.toLong(data, off, 4, state.getSentSignedOnTime());
            off += 4;
            
            // we need to pad this so we're at the encryption boundary
            int mod = (off + Signature.SIGNATURE_BYTES) & 0x0f;
            if (mod != 0) {
                int paddingRequired = 16 - mod;
                // add an arbitrary number of 16byte pad blocks too ???
                _context.random().nextBytes(data, off, paddingRequired);
                off += paddingRequired;
            }
            
            // BUG: NPE here if null signature
            System.arraycopy(state.getSentSignature().getData(), 0, data, off, Signature.SIGNATURE_BYTES);
            off += Signature.SIGNATURE_BYTES;
        } else {
            // We never get here (see above)

            // nothing more to add beyond the identity fragment
            // pad up so we're on the encryption boundary
            off = pad1(data, off);
        } 
        off = pad2(data, off);
        pkt.setLength(off);
        authenticate(packet, state.getCipherKey(), state.getMACKey());
        setTo(packet, to, state.getSentPort());